Skip to content

Conversation

@gregshue
Copy link

This PR contains a new sample demonstrating a standard Zephyr use case not currently supported. The successive commits demonstrate the successive build FAILURES encountered until a minimal(?) solution was found to support the new sample.

Fundamentally these reveal that in order to support an externally configurable, composable solution the MCUBoot source build file cannot contain the find_package(Zephyr ...) command. In other words, the reusable sources build file (CMakeLists.txt) must be in a different directory than the project configuration build file (CMakeLists.txt). Similarly, the Kconfig files within the module sources tree cannot also be a top-level project Kconfig definition file (otherwise causing recursive sourcing of Kconfig.zephyr).

This may not be the actual minimal solution for the current implementation of the Zephyr build system, but it seems to be the smallest implementation that is consistent with the Zephyr build system features, paradigms, and recommended/expected behaviors.

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 3494cc0 to af0cf83 Compare October 12, 2022 02:29
@gregshue
Copy link
Author

I don't like having to copy the local *.conf and board/ files into the new sample, but a general pattern must work across modules. Once Zephyr PR #47638 is fully approved and merged, then these files could be referenced rather than copied.

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from af0cf83 to 883b240 Compare October 12, 2022 21:39
@gregshue
Copy link
Author

This PR implementation has been cleaned up and existing functional builds verified and documented at every commit. (NOTE: Make-ing mcuboot/sample/zephyr did not succeed at the base of this PR, so it was not part of the verification process.)

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 883b240 to 518cb95 Compare October 13, 2022 16:25
@gregshue
Copy link
Author

The push above takes advantage of the just-merged of the fix for Zephyr's issue #41830, enabling use of ZEPHYR__MODULE_DIR in CONF_FILE, OVERLAY_CONFIG, and DTC_OVERLAY_FILE before find_package().

It also takes advantage of the APPLICATION_CONFIG_DIR.

Together these reduced that solution to 17 files (touched and created).

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch 2 times, most recently from 0efb83c to 6f4c42b Compare October 18, 2022 19:26
@gustavonihei gustavonihei added the area: zephyr Affects the Zephyr port label Oct 18, 2022
@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 6f4c42b to e46d74a Compare October 19, 2022 19:27
Copy link
Member

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add zephyr/samples/tfm_integration/psa_crypto as a dir you test. This will test a TF-M build while also uses MCUboot.

Copy link
Member

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the copy of the board files, before committing this, can we make a Zephyr issue, so we can reference that in this commit. Then, once this merges, we can modify the Zephyr issue to point back to this commit, to demonstrate why the fix is needed.

Copy link
Member

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename mcuboot_svc to mcuboot_app, if anything it isn't abbreviated, and I think a little clearer what is in it.

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from e46d74a to 73414e4 Compare October 25, 2022 23:34
@gregshue
Copy link
Author

The following changes address comments above:

I think that addresses all feedback so far.

@gregshue gregshue requested a review from d3zd3z October 25, 2022 23:39
@gregshue
Copy link
Author

@nvlsianpu Since you missed today's TSC meeting where we reviewed the minimum implementation in detail, do you have any feedback?

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch 3 times, most recently from 7e3d085 to 0472e72 Compare October 27, 2022 18:45
@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 0472e72 to 137a71a Compare November 4, 2022 19:48
Copy link
Collaborator

@nordicjm nordicjm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces the follow when configuring boot/zephyr:

warning: MBEDTLS_CFG_FILE (defined at modules/mbedtls/Kconfig:50,
/tmp/aa/bootloader/mcuboot/zephyr/Kconfig:170, modules/mbedtls/Kconfig:50) was assigned the value
'mcuboot-mbedtls-cfg.h' but got the value 'config-tls-generic.h'. See
http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_MBEDTLS_CFG_FILE and/or look up
MBEDTLS_CFG_FILE in the menuconfig/guiconfig interface. The Application Development Primer, Setting
Configuration Values, and Kconfig - Tips and Best Practices sections of the manual might be helpful
too.

This configuration should not be failing to be set

@gregshue
Copy link
Author

gregshue commented Nov 9, 2022

@nordicjm What is the command line/test case you were building that shows the warning?

@nordicjm
Copy link
Collaborator

nordicjm commented Nov 9, 2022

@nordicjm What is the command line/test case you were building that shows the warning?

cmake -GNinja -DBOARD=nrf52dk_nrf52832 ..

@gregshue
Copy link
Author

gregshue commented Nov 9, 2022

cmake -GNinja -DBOARD=nrf52dk_nrf52832 ..

Which was built from where?

@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 8e326dd to 4784976 Compare November 16, 2022 19:34
@@ -0,0 +1,2 @@
CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why this the nrf52840dk_nrf52840_cc310_ecdsa.conf is outside of boards dir?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is located in the same place as in $mcuboot/boot/zephyr/. Changing this was not necessary for this minimal refactor (just like cleaning out unnecessary default n in Kconfigs).

@nordicjm nordicjm removed their assignment Nov 17, 2022
@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 4784976 to 42ce73d Compare November 17, 2022 16:46
Copy link
Collaborator

@nvlsianpu nvlsianpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DNM] This need be considered by zephyr-rtos/zephyr maintainers

@nvlsianpu nvlsianpu added the [DNM] Do Not Merge label Nov 18, 2022
@gregshue
Copy link
Author

gregshue commented Nov 18, 2022

[DNM] This need be considered by zephyr-rtos/zephyr maintainers

Why?!? Notice:

  • MCUboot is a downstream project from Zephyr, dependency-wise. (Even Anas has described it that way). It is also downstream of multiple other OS'.
  • Zephyr has already elected to provide a fork of the MCUboot module. In this Zephyr Project PR comment Anas describes exactly why Zephyr has a fork - so Zephyr can make changes as they deem necessary.
  • All the changes here are in alignment with the current Zephyr build system, patterns illustrated or implied in Zephyr's example-application repository.
  • All the changes here have already been verified to work with all the Zephyr-provided test suites that I am aware are relevant.
  • Zephyr's SOF module fork has already started to put the Zephyr directory tree within $module/zephyr/.
  • Zephyr's current MAINTAINERS file lists the maintainers as d3zd3z, de-nordic, nordicjm. These have already participated in the review.

In other words, they have effectively already considered and approved these types of changes, and it is the responsibility of the Zephyr mcuboot fork maintainer to adjust their fork as necessary when they update the fork with changes from the upstream project.

(Edit 1 start)
Please remove the baseless [DNM].

If the goal of DNM is to get Zephyr Project feedback toward being a recommended general OOT module pattern, then please put a short time limit on DNM and identify which Zephyr working group will be approached for the feedback. Rolling out initial Zephyr-based testing of mcuboot logic is unblocked by this PR, so we shouldn't wait long.

(Edit 1 end)

Copy link
Contributor

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very intrusive change in the build system in my opinion.

It moves a lot of code around, apparently because of this motivation:

Fundamentally these reveal that in order to support an externally configurable, composable solution the MCUBoot source build file cannot contain the find_package(Zephyr ...) command. In other words, the reusable sources build file (CMakeLists.txt) must be in a different directory than the project configuration build file (CMakeLists.txt). Similarly, the Kconfig files within the module sources tree cannot also be a top-level project Kconfig definition file (otherwise causing recursive sourcing of Kconfig.zephyr).

Zephyr already today supports the use of APPLICATION_CONFIG_DIR which means that any user of MCUboot can create a custom configuration dir outside MCUboot for local tweaking of MCUboot.

For example by creating app_conf_test folder and pass that information to the build system, like this:

$ cmake -GNinja -DBOARD=nrf52840dk_nrf52840 -Bbuild boot/zephyr/ -DAPPLICATION_CONFIG_DIR=(pwd)/app_conf_test
Loading Zephyr default modules (Zephyr workspace).
-- Application: /projects/github/ncs/bootloader/mcuboot/boot/zephyr
...
-- Found BOARD.dts: /projects/github/ncs/zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts
-- Found devicetree overlay: /projects/github/ncs/bootloader/mcuboot/app_conf_test/app.overlay
-- Generated zephyr.dts: /projects/github/ncs/bootloader/mcuboot/build/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /projects/github/ncs/bootloader/mcuboot/build/zephyr/include/generated/devicetree_generated.h
-- Including generated dts.cmake file: /projects/github/ncs/bootloader/mcuboot/build/zephyr/dts.cmake
Parsing /projects/github/ncs/bootloader/mcuboot/boot/zephyr/Kconfig
Loaded configuration '/projects/github/ncs/zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig'
Merged configuration '/projects/github/ncs/bootloader/mcuboot/app_conf_test/prj.conf'
Merged configuration '/projects/github/ncs/bootloader/mcuboot/app_conf_test/boards/nrf52840dk_nrf52840.conf'
...

Notice how devicetree overlay and config files are being picked up from the app_conf_test/ and app_conf_test/boards folders in above log messages.

One can even create a custom CMakeLists.txt file and do customization in there before sourcing boot/zephyr/CMakeLists.txt file if such is needed.

For time being, I see this PR as a I don't understand / like the current structure therefore I would like this structure instead. type of PR.

Maybe I have missed something fundamental regarding this PR, so if that is the case I urge @gregshue to instead create much smaller PRs with a clear objective of what is the exact goal.
For example a PR that take a subpart of the CMake code into a dedicate library for re-usability with a clear purpose.

Note, I have only made a few code comments, but I have discovered a lot of places that I cannot approve as they are proposed currently, but imo it make little sense to point out all those places atm, as the overall state of PR is far from going into such details.

Note: regarding the use of APPLICATION_CONFIG_DIR there is a flaw in MCUboot which I have addressed here: #1522

#


# Option to build the project with the MCUBoot application
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this definition and criteria, mcuboot was a downstream module before I ever started. It just wasn't represented that way in the build system.

MCUboot is a Zephyr module containing the MCUboot application.

The configuration of the MCUboot application in Zephyr context starts at the Kconfig file, but that is the MCUboot Kconfig file, it's not a Kconfig file for using MCUboot as a subsys / library in the Zephyr build system.

And I don't see a reason why this should change

The current design builds a bootloader independent of the application.
With your design changes, then you start building and linking the application together with the bootloader in the process, and thus they start to be tightly coupled with all the cons of address spacing and separating the two parts in the linker script.

This is more vulnerable to mistakes and can be risky wrt. updates, compared to building (and flashing) just the bootloader, and doing so independently of the application.

Of course nothing prevents anyone from doing so in their own project, like TF-M builds MCUboot without using Zephyr.
Ref: https://github.com/zephyrproject-rtos/trusted-firmware-m/blob/master/bl2/ext/mcuboot/CMakeLists.txt

but I believe that the Zephyr integration ought to stick to current process.

Providing both ways will add additional maintenance burden and has higher risk of confusing users.
So far I'm not convinced of the benefits of approving the changes in this PR.

set(KEY_FILE ${CONF_DIR}/${CONFIG_BOOT_SIGNATURE_KEY_FILE})
else()
set(KEY_FILE ${MCUBOOT_DIR}/${CONFIG_BOOT_SIGNATURE_KEY_FILE})
set(KEY_FILE ${ZEPHYR_MCUBOOT_MODULE_DIR}/${CONFIG_BOOT_SIGNATURE_KEY_FILE})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just discovered: #1492 (comment)

which imo should never have been merged.
MCUboot can be used by multiple projects, project which themselves is used by Zephyr (or which uses Zephyr).

This means a complete project can include multiple revisions of MCUboot.

One such case is Zephyr, which uses TF-M, which again includes a specific revision of MCUboot.
A MCUboot revision which is different from the MCUboot revision used by Zephyr.

But as Zephyr module, there can only be a single module with the MCUBOOT name, which means this is not gonna work in more complex setups.

Comment on lines +14 to +15
# Verify the module name is set correctly
set(expected_module_name "mcuboot")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, mcuboot can be used in a project in multiple revisions.

For example a multi-core project may use mcuboot as bootloader in one core, with revision A, but have TF-M with secure bootloader as revision B on other core.
Two distinguish the two cases, each revision can be placed in different folder and thereby be referred to by different module names.

This is also the reason that a module should always refer internally to itself as: ZEPHYR_CURRENT_MODULE_DIR.

One reason why this should never have been merged: #1492

Comment on lines +27 to +29
# Do not allow in source builds
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not start to use internal and undocumented CMake features without fully understanding what they are doing.

Just the fact that you apply both flags shows lack of knowledge on their purpose.

Also note, those two flags will now be set for any Zephyr now, not just mcuboot, so really not the right place to do this.

Besides that, CMakeCache.txt and CMakeFiles folder are still being created.
More info: https://gitlab.kitware.com/cmake/cmake/-/issues/18403

Note: in-source builds are not recommended, but that doesn't mean this is the right place or way to try and prevent this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everybody begins knowing nothing. I'll remove them.

@@ -0,0 +1,234 @@
# CMakeLists.txt for building mcuboot as a Zephyr project
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an application specific CMakeLists.txt file suddenly being moved into Zephyr module CMake processed code.

Existing code could surely benefit from a cleanup, but just moving the code really doesn't improve anything.

In fact, it makes a lot of things much harder cause now a git blame shows e456522 everywhere.

I currently see no gain in this commit.
If instead parts of this file where made into re-usable library, then part of change could maybe make sense, but I would much prefer to see such small and clean PR, than this massive and code intrusive change everywhere.

../include
../../zephyr/include
zephyr_include_directories(MCUBOOT_BOOTUTIL INTERFACE
${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/bootutil/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code is loaded as a Zephyr module, so it should not refer to itself using its own module name, but ZEPHYR_CURRENT_MODULE_DIR.

@nvlsianpu
Copy link
Collaborator

@gregshue I see your points on that mcuboot is a downstream project for zephyr. Having a fork for mcuboot in zephyr-rtos GH doesn't determine how the maintenance is preformed. I want to have 1:1 relation, so fare this approach have been working fine. On every synchronization of zephyr-rtos/mcuboot with the origin the code diff is expected to be empty.

I design this PR with DNM as this change have critical severity for the zephyr-project and every projects which leverage the mcuboot zephyr port.

As you can see we have already review from build system expert.

@gregshue
Copy link
Author

Nothing in this change breaks the zephyr builds. As Ana's has said, Zephyr needs to make decisions independent of downstream concerns. In fact, this change came about because the current implementation does not fully support the range of user needs supported by Zephyr.

Specifically, What changes here are critically severe?

@tejlmand
Copy link
Contributor

Nothing in this change breaks the zephyr builds.

In which case any PR should just blindly be approved, or what is your point ?

This PR is not simply trying to improve current code, but moving code around irrespective of the current design.
Although part of existing code can surely be improved, the move proposed in this PR just makes things even more messy.

As Ana's has said, Zephyr needs to make decisions independent of downstream concerns.

and that is a carte-blanche to request changes directly in the mcuboot repository, or what is your point ?
Try to compare the change @nashif is requesting, which is a single config line in a prj.conf to the major changes requested in this PR.

In fact, this change came about because the current implementation does not fully support the range of user needs supported by Zephyr.

Exactly which use-case is not properly handled by the description provided here:
#1489 (review)

and why can such use-case not be done in a less-intrusive way ?

@gregshue
Copy link
Author

Maybe I have missed something fundamental regarding this PR, ...

You have.

I urge @gregshue to instead create much smaller PRs with a clear objective of what is the exact goal.

Good suggestion. Look at PR #1524

MCUboot is the manifest repository of my workspace. Building this this PR from the root of my workspace with either current mcuboot main branch or after manually applying the changes of #1522 generates the same build failures.

'''
west build -p always -b nrf52840dk_nrf52840 mcuboot/zephyr/samples/modules/mcuboot/mcuboot_external_config/
'''

gives two sets of warnings (even though building mcuboot/boot/zephyr builds cleanly):

  • (1x) warning: MBEDTLS_CFG_FILE (defined at modules/mbedtls/Kconfig:50, modules/mbedtls/Kconfig:50) was assigned the value 'mcuboot-mbedtls-cfg.h' but to the value ''. Check these unsatisfied dependencies: ((MBEDTLS_BUILTIN && MBEDTLS) || (MBEDTLS_BUILTIN && MBEDTLS && 0)) (=n).
  • (12x) warning: attempt to assign the value 'n' to the undefined symbol ...

I cannot even reach the point of verifying my local board settings cascade with those in APPLICATION_CONFIG_DIR.

MCUboot is a Zephyr module containing the MCUboot application.

The MCUboot zephyr module also contains the mcuboot bootutil library.

The current design builds a bootloader independent of the application.
With your design changes, then you start building and linking the application together with the bootloader in the process, and thus they start to be tightly coupled with all the cons of address spacing and separating the two parts in the linker script.

This is where you misunderstood what this does. This still builds and flashes the bootloader independently of the application. According to the zephyr.map files, this refactoring only does the following w.r.t. linking:

  • app/libapp.a is reduced to have keys.c.obj. All the other object files go into zephyr/libzephyr.a.
  • mcuboot/libmcuboot_util.a becomes mcuboot/subsys/mcuboot_util/libmcuboot_util.a.

This is an application specific CMakeLists.txt file suddenly being moved into Zephyr module CMake processed code.

AFAICT the only part of the original CMakeLists.txt that makes this an application CMakeLists.txt is 'find_project(Zephyr ...)'. The rest could be refactored into include()ed files, or into subsystems. From my many years of experience in this area, this will be much easier to maintain if the "application" logic is refactored as a subsystem.

just moving the code really doesn't improve anything.

... except for fixing the use cases that the current configuration doesn't support.

In which case any PR should just blindly be approved, or what is your point ?

The answer didn't identify what changes "have critical severity for the zephyr-project". It doesn't seem to be a build issue.

but moving code around irrespective of the current design.

The current design doesn't meet the breadth of user needs (e.g., mine, as shown by the samples).

the move proposed in this PR just makes things even more messy.

I actually find it far more orderly, consistent, scalable, and applicable to other downstream modules than the current design.

and why can such use-case not be done in a less-intrusive way ?

It may be able to be done in a less intrusive way, but this is a way that follows existing patterns in Zephyr and example-application, introduces more alignment with the Zephyr build/configuration system, and can be applied in general to downstream repositories.

Show me another way to meet this use case and then let's evaluate the approaches based on overall merit.

@nordicjm
Copy link
Collaborator

MCUboot is the manifest repository of my workspace

Then your project is completely wrong from the start.

@tejlmand
Copy link
Contributor

tejlmand commented Nov 22, 2022

I urge @gregshue to instead create much smaller PRs with a clear objective of what is the exact goal.

Good suggestion. Look at PR #1524

Thanks.

The linked PR (#1524) actual reveals that this PR (#1489) originates from a lack of understanding on how MCUboot is integrated into Zephyr and how the build system (CMake and Kconfig) it works.

@gregshue
Copy link
Author

Then your project is completely wrong from the start.

That statement directly contradicts Zephyr support for T2 topology and what is done in Zephyr Project's example-application repository. Try again.

The linked PR (#1524) actual reveals that this PR (#1489) originates from a lack of understanding on how MCUboot is integrated into Zephyr and how the build system (CMake and Kconfig) it works.

Actually, you have this backwards. The linked PR is a use case that the MCUboot integration must support (i.e., requirement) - though I think top-level CMakeLists.txt files should never be include()ed in other projects.

@tejlmand
Copy link
Contributor

tejlmand commented Nov 22, 2022

Actually, you have this backwards. The linked PR is a use case that the MCUboot integration must support

did you read the comments I wrote and tried it out ? (#1524 (review))
The use-case of configuring MCUboot externally is possible, I even created a branch for you.
https://github.com/tejlmand/mcuboot/tree/mcuboot/review_1524

If you want to wrap that inside a CMakeLists.txt file, then that is also possible and works as expected.
Just understand how the system is intended to work.

though I think top-level CMakeLists.txt files should never be include()ed in other projects.

So use ExternalProject_Add() or add_subdirectory().
There exists several ways, but this (#1489) is a PR under review and not about helping you to understand the system.
So now we back at the fact that your use-case is supported:

So there are plenty of ways that you can customize MCUboot.
Notice, the sample in https://github.com/zephyrproject-rtos/mcuboot/tree/main/boot/zephyr is a reference sample on how Zephyr integrates MCUboot, but you can do that in a myriad different ways.

Either by using ways already supported by the Zephyr CMake / Kconfig build and configuration system which even allows a large degree of freedom on how, copy the MCUboot sample to own repo and make adjustments or go completely independent of the Zephyr build system, like espressif case, and still build MCUboot so that it works with Zephyr.

But #1489 is a PR where you propose yet one more variant in customization.
It is not a guideline on how to carry out above possibilities.

I keep my 👎 on this PR as I don't see the need to support and maintain yet one more way of integrating MCUboot with Zephyr.
One more way that risks confusing users on how to use the system.
More risk of corner cases.
One more way that must be tested, documented, maintain.

MCUboot and MCUboot with Zephyr is already very flexible and support large degree of customization (although documentation on how to actually do this can probably be improved).

@gregshue
Copy link
Author

did you read the comments I wrote and tried it out ?

Apparently not well enough. Now that I have here's what I found:

  • I successfully built from my mcuboot-manifested workspace with the following command:
    '''
    west build -p always -b nrf52840dk_nrf52840 mcuboot/boot/zephyr
    -DAPPLICATION_CONFIG_DIR=(pwd)/mcuboot/samples/zephyr/mcuboot_external_configuration
    '''

  • I adding a local CMakeLists.txt (include(${CMAKE_CURRENT_LIST_DIR}/../../../boot/zephyr/CMakeLists.txt)` and running the following command:
    '''
    west build -p always -b nrf52840dk_nrf52840 mcuboot/samples/zephyr/mcuboot_external_configuration
    '''
    The build FAILED, reporting warnings on:

    1. Kconfigs being assigned non-'n' values but having value 'n'
    2. attempt to assign the value 'n' to the undefined symbol ...;
  • I copied $mcuboot/boot/zephyr/Kconfig locally, fixed up the rsource "Kconfig.serial_recovery" to include the relative path, and attempted the command immediately above. The build failed with "No such file or directory: TINYCRYPT_DIR: '/home/zephyr/mcuboot_review/mcuboot/samples/ext/tinycrypt/lib'

Clearly, $mcuboot/boot/zephyr/CMakeLists.txt is not designed to be included`

So use ExternalProject_Add() or add_subdirectory().

Notice that both require a path. This is a problem for my use case, where the top-level CMakeLists.txt and configurations exist in a different repository than mcuboot or zephyr, and no command line options other than project path is allowed, and I am not allowed to change the mcuboot repository. (In my case even the board needs to be set through a file under SCM control.)

AFAICT, your suggestions still do not support my use case (building from a config entirely in a different repo).

You can create your own custom CMakeLists.txt and fully control MCUboot any way you like

I can, but I shouldn't have to. I am following a widely-presumed use case.

But #1489 is a PR where you propose yet one more variant in customization.

Unlike APPLICATION_CONFIG_DIR, the pattern of customization in this PR is not new to the Zephyr Project. Rather, this PR refactors the implementation to properly support Zephyr's standard pattern of customization. It also aligns with Zephyr's definition of "application", which does not require any application-unique logic.

How about this: Please show me how build and configure a bootloader build from a CMakeLists.txt and prj.conf under example-application (e.g., west build -b nrf52840dk_nrf52840 $example-application/mcuboot_external_configuration), because I don't think you can do it without modifying zephyr/ or mcuboot/, or putting restrictions on the workspace directory tree.

@tejlmand
Copy link
Contributor

tejlmand commented Nov 23, 2022

How about this: Please show me how build and configure a bootloader build from a CMakeLists.txt and prj.conf under example-application (e.g., west build -b nrf52840dk_nrf52840 $example-application/mcuboot_external_configuration), because

This is a PR review, so basically such a request should be posted at the proper channel, but as it just requires 5 CMake commands cmake_minimum_required(), project(), find_package(), include(), and ExternalProject_Add() then I have done you the courtesy of creating a repo with a freestanding application.
If it can work as a freestanding application, then it can also work as a workspace application.
You need to add this commit on top of mcuboot #1522 .
If this fails for you, please read the getting started on how to properly install Zephyr, or take any further questions to the proper channel (Discord).

See here:
https://github.com/tejlmand/oot_mcuboot_showcasing

$ cmake -GNinja -DBOARD=nrf52840dk_nrf52840 -Bbuild .
Loading Zephyr module(s) (Freestanding): west zephyr_module
...
-- Build files have been written to: /tmp/oot_mcuboot_external_configuration/build
$ ninja -C build
ninja: Entering directory `build'
[5/8] Performing configure step for 'mcuboot'
Loading Zephyr default modules (Zephyr workspace).
-- Application: /projects/github/ncs/bootloader/mcuboot/boot/zephyr
...
-- Found devicetree overlay: /tmp/oot_mcuboot_external_configuration/app.overlay
...
Loaded configuration '/projects/github/ncs/zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840_defconfig'
Merged configuration '/tmp/oot_mcuboot_external_configuration/prj.conf'
Merged configuration '/tmp/oot_mcuboot_external_configuration/boards/nrf52840dk_nrf52840.conf'
...
271/271] Linking C executable zephyr/zephyr.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       40092 B        48 KB     81.57%
             RAM:       23808 B       256 KB      9.08%
        IDT_LIST:          0 GB         2 KB      0.00%
[8/8] Completed 'mcuboot'

I don't think you can do it without modifying zephyr/ or mcuboot/, or putting restrictions on the workspace directory tree.

As I have said before, I don't think you have fully understood the power of the current design and infrastructure of the build system.

Can we close this topic and PR now ?

@gregshue
Copy link
Author

Thank you for the example. I did not want to assume that ${ZEPHYR_<moduleNameUpper}_MODULE_DIR} was always going to be available for use in ExternalProject_Add()`.

I was able to successfully build this stand-alone, when added into example-application as the manifest repositoryl

BUT ...

The build failed when I also passed in -DCONF_FILE=.... Here are the results I got:

  • "-DCONF_FILE=prj.conf": picks up local prj.conf; does NOT pick up either local or remote boards/nrf52840dk_nrf52840.conf; did not generate the proper size image.
  • "-DCONF_FILE=${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/zephyr/prj.conf": picks up $mcuboot/boot/zephyr/prj.conf; does NOT pick up either local or remote boards/nrf52840dk_nrf52840.conf; did not generate the proper size image
  • "-DCONF_FILE=${ZEPHYR_MCUBOOT_MODULE_DIR/boot/zephyr/prj.conf;prj.conf": picks up $mcuboot/boot/zephyr/prj.conf; does NOT pick up local prj.conf does not pick up remote and local boards/nrf52840dk_nrf52840.conf; did not generate the proper size image.

So ... both approaches suffer from common failures in the build system forcing the duplication of config files/settings.

Now we're down to comparing the actual approaches to support reuse of logic currently private to an application. We're making headway!

First, notice that Zephyr's glossary definition of application does not require any logic or data unique to it. As you know, the build system works fine if an application provides a zero-byte C source file. We need to discuss the reuse of logic (e.g., library/subsystem) separate from the reuse of an application (configuration and build files).

Second, in general no one is able to predict when logic in one application will need to be reused in another. Having experienced the evolution and growth of a software product line over many generations. I am a witness that functionality we never expected to be used in a different application needed to be refactored out for sharing. The strategic direction is to expect any/all logic will end up being shared across multiple applications.

Third, the mcuboot module already exposes bootutil as a subsystem through module.yml. It is already configurable through Kconfigs. The bootutil subsystem/library already has a zephyr unique CMakeLists.txt. None of these concepts are introduced with this PR. In fact, this PR is refactoring the boot/zephyr/ build files to follow these existing concepts and patterns to expose the logic to be reused in the existing/expected way.

Fourth, it sounds like APPLICATION_CONFIG_DIR was introduced as a hotfix for a specific use case. The pattern implied by this functionality is to attempt to reuse logic and build files that may not have been designed for reuse. (See above issues.) I expect this tactic was straight forward but strategically leads to a more fragile ecosystem than one where all code to reuse is created and maintained as intentionally reusable code.

With all that I have learned about your recommendations and experienced myself over the years, it seems to me having MCUboot refactor out reusable code into subsystems (as done in this PR) is the wiser solution for both the short and long term.

Evaluating the complexity of this PR in terms of touched file count is really inappropriate. Whether one file is moved or an entire directory is should not matter. This PR is simply:

  1. splitting files apart based on fragments of reuse
  2. locating the reusable portions in the expected location for reusable content
  3. providing a standard sample/test case for automatic (re)verification
  4. putting all this in the organizational structure that is naturally understood/expected/debuggable by all working in the Zephyr ecosystem.

Honestly, your steadfast advocacy of APPLICATION_CONFIG_DIR sounds like I don't understand / like the current zephyr platform architecture therefore I'll promote this structure instead. This will likely cause you problems when the build system has to be "qualified" for the auditable branch. You, my friend, will have to tackle the whole of software engineering to do that. You might as well take the free course LFD-116 sooner rather than later.

Now, are you ready to approve this PR so we can move on to filling out mcuboot test cases?

@tejlmand
Copy link
Contributor

"-DCONF_FILE=prj.conf": picks up local prj.conf; does NOT pick up either local or remote boards/nrf52840dk_nrf52840.conf; did not generate the proper size image.

Did you fail to read this:

If this fails for you, please read the getting started on how to properly install Zephyr, or take any further questions to the proper channel (Discord).

that's how -DCONF_FILE is documented to work.
Using CONF_FILE is opting-out of the automatic process.
go read the docs:
https://docs.zephyrproject.org/latest/build/kconfig/setting.html#the-initial-configuration
or read the comment I gave you here:
#1524 (comment)

@tejlmand
Copy link
Contributor

tejlmand commented Nov 24, 2022

it sounds like APPLICATION_CONFIG_DIR was introduced as a hotfix for a specific use case.

Quite the opposite, it's generic and scalable as it works for any app, from hello world, to hci_rpmsg, and even to MCUboot.
And can be used for any board.

Your proposal is MCUboot specific and tailored exactly to your needs.
It makes application specific Kconfigs available in the general Kconfig tree, not only MCUboot app but all applications now has those settings available.

Imagine each and every sample in Zephyr want to have their settings available in the global Kconfig space.
What a mess and nightmare that will become.

@gregshue
Copy link
Author

that's how -DCONF_FILE is documented to work.

From the perspective of multiple stakeholders in Zephyr, your design is not valid no matter how much it has been verified. See below.

(The design also doesn't fully meet your specification, as it didn't properly parse a list of multiple prj.conf.)

Quite the opposite, it's generic and scalable as it works for any app, from hello world, to hci_rpmsg, and even to MCUboot.
And can be used for any board.

The design of CONF_FILE rules do not support the SOLID design principles, specifically the Liskov Substitution Principle. Thus it is not scalable to multiple levels of project derivation. In case you hadn't noticed it the Zephyr ecosystem architecture is a client-server organized architecture of objects. Notice how:

Your proposal is MCUboot specific and tailored exactly to your needs.

How does aligning with the general pattern of Zephyr modularity make it specific and tailored to my needs? Try again.

It makes application specific Kconfigs available in the general Kconfig tree, not only MCUboot app but all applications now has those settings available.

Your approach does the same thing in a less obvious way. The oot configuration and CMakeLists.txt constitutes a separate application per Zephyr's definition. ANY/all applications already have them available. Once the code is reused the settings are no longer application specific. My approach exposes the Kconfigs controlling the reusable logic in exactly the same way as happens in other downstream modules - following the solution supported by Zephyr.

Anyone need to be able to combine the MCUboot app logic with a ztest suite. By the Zephyr definition this is a different application. I also need to be able to combine MCUboot app logic with other proprietary logic - without touching the MCUboot repository. Fundamentally, all certifiable logic will be shared with test applications. The typical case will be sharing that logic with a ztest application.

Imagine each and every sample in Zephyr want to have their settings available in the global Kconfig space.
What a mess and nightmare that will become.

It doesn't have to be, and Zephyr header include guards have already illustrated the solution. The Kconfigs simply need to be prefixed with the moduleName+pathToDefinition. This pattern of solution has been practiced for decades.

xiaoxiang781216 and others added 4 commits December 1, 2022 14:45
- Add prompt to MCUBOOT Kconfig and default 'n'
- Add prompt to MCUBOOT_APP Kconfig and default 'n'
- Add prompt to MCUBOOT_DEVICE_SETTINGS_ Kconfig and default 'n'.
  These device settings rules need to not be applied for the
  psa_crypto build.
- Add boot/zephyr/Kconfig reference to module.yml
- Relocate module Kconfig into mcuboot/zephyr/
- Relocate module-level Kconfig declarations into the module's
  zephyr/ subdirectory so that it is visible for external build
  configurations.  Removed sourcing of Kconfig.zephyr
- Restore sourcing of Kconfig.zephyr to stripped boot/zephyr/Kconfig.

The MCUBOOT Kconfig seems to control the inclusion of MCUboot
application code in the Zephyr build.. Because this name matches
the module and an alternate name was used to include MCUboot's
bootutil package the name usage is a bit unorthodox.

An ortodox and scalable pattern is for a Kconfig matching the
module name to control the exposure of the module itself
(e.g., the public headers).  The first step in this transition is
to make MCUBOOT public and default to 'n'.  Defaulting to 'n' will
prevent this module with interfering with other existing builds.

Incremental verification:

1. (Pass) west build -p always -b nrf52840dk_nrf52840 mcuboot/boot/zephyr/
2. (Pass) ./zephyr/scripts/twister --testsuite-root mcuboot/boot/zephyr/
3. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/tfm_integration/psa_crypto/
4. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/tests/subsys/dfu/
5. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/subsys/mgmt/mcumgr/smp_svr/

Signed-off-by: Xiang Xiao <[email protected]>
Signed-off-by: Gregory Shue <[email protected]>
The Zephyr build system expects CMakeLists.txt to be only
in directories beneath the module-level CMakeLists.txt.  The
solution most consistent with Zephyr led to putting the
subsystem-specific build logic within the `zephyr/` subdirectory.
This also led to relocating the `boot/bootutil/zephyr/CMakelists.txt`.
It also led to adding an explicit `name:` setting in `module.yml`
to ensure files can consistently reference the module independent of
where the module is mounted.
Created a module-level CMakeLists.txt for extending the include paths
to find "mcuboot-mbedtls-cfg.h" within the boot/zephyr component.

Incremental verification:

1. (Pass) west build -p always -b nrf52840dk_nrf52840 mcuboot/boot/zephyr/
2. (Pass) ./zephyr/scripts/twister --testsuite-root mcuboot/boot/zephyr/
3. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/tfm_integration/psa_crypto/
4. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/tests/subsys/dfu/
5. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/subsys/mgmt/mcumgr/smp_svr/

Signed-off-by: Gregory Shue <[email protected]>

Fixes
Extract reusable portions of boot/zephyr for
use in other mcuboot builds:

- mcuboot signature key file generation build logic
- mcuboot zephyr runner mass erase hooks

Verification:

1. (Pass) west build -p always -b nrf52840dk_nrf52840 mcuboot/boot/zephyr/
2. (Pass) ./zephyr/scripts/twister --testsuite-root mcuboot/boot/zephyr/
3. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/tfm_integration/psa_crypto/
4. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/tests/subsys/dfu/
5. (Pass) ./zephyr/scripts/twister --testsuite-root zephyr/samples/subsys/mgmt/mcumgr/smp_svr/

Signed-off-by: Gregory Shue <[email protected]>
Created a sample of how to configure MCUBoot build from an
external repository.  This sample provides no `main()` definition
and reuses all logic from MCUBoot and other repositories.  The
functionality matches the existing functionality of mcuboot/boot/zephyr.

The sample is located within `$mcuboot/zephyr/samples/modules/mcuboot/`
so that the directory path matches that used in Zephyr for samples
of external modules.  The directory name `mcuboot_external_config`
intentionally begins with the module name to help avoid futures
conflict with samples that may be defined in other repositories.
Together, this pattern supports easy integration of this sample
documentation with sample documentation in Zephyr.

NOTE: This commit required copying board and .conf files from
mcuboot/boot/zephyr because the _current_ zephyr build system
(about v3.2.0) does not fully support using APPLICATION_CONFIG_DIR
with a list of files/directories in CONF_FILE and with boards/
beneath those settings.  When APPLICATION_CONF_DIR was set to
reference mcuboot/boot/zephyr/ and CONF_FILE referenced
APPLICATION_CONFIG_DIR then here, the boot config did not pick
up a board-specific configuration setting from APPLICATION_CONFIG_DIR,
resulting in FLASH going from ~40000 to ~45000 bytes.

  This is captured in Zephyr Issue #51621.

Verification:

1. (Pass) west build -p always -b nrf52840dk_nrf52840 \
            mcuboot/zephyr/samples/modules/mcuboot/mcuboot_external_config/
2. (Pass) ./zephyr/scripts/twister --testsuite-root mcuboot/zephyr/samples/

Fixes mcu-tools#1410

Signed-off-by: Gregory Shue <[email protected]>
@gregshue gregshue force-pushed the feature/1410_min_refactor_zephyr_port branch from 42ce73d to e0afbd1 Compare December 2, 2022 01:01
@github-actions
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the stale label May 31, 2023
@github-actions github-actions bot closed this Jun 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: zephyr Affects the Zephyr port [DNM] Do Not Merge stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants